from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QPushButton,
                           QLabel, QScrollArea, QFrame, QTreeWidget, QTreeWidgetItem,
                           QSplitter, QTextEdit, QMessageBox, QSlider, QLineEdit, QRadioButton,
                           QButtonGroup, QFileDialog, QScrollBar, QInputDialog)
from PyQt6.QtCore import Qt, pyqtSignal, QTimer, QEventLoop
from PyQt6.QtGui import QIcon, QFont, QTextBlockFormat, QTextCursor, QTextFormat, QTextOption, QShortcut, QKeySequence, QTextCharFormat, QFontMetrics, QPixmap, QTextDocument, QColor
import re
import json
from pathlib import Path
from PyQt6.QtWidgets import QApplication
import time
import uuid
from .bookmark_list_dialog import BookmarkListDialog

class SmoothScrollBar(QScrollBar):
    def __init__(self, parent=None):
        super().__init__(Qt.Orientation.Vertical, parent)
        self.setFocusPolicy(Qt.FocusPolicy.NoFocus)
        
    def wheelEvent(self, event):
        """处理鼠标滚轮事件"""
        # 计算滚动距离，根据滚轮delta值调整滚动速度
        numDegrees = event.angleDelta().y() / 8
        numSteps = numDegrees / 15.0
        
        # 计算新的滚动位置
        currentValue = self.value()
        newValue = currentValue - (numSteps * self.singleStep())
        
        # 确保滚动值在有效范围内
        newValue = max(self.minimum(), min(newValue, self.maximum()))
        
        # 立即更新滚动条位置，无动画
        self.setValue(int(newValue))
        
        # 阻止事件继续传播
        event.accept()

class ReaderWidget(QWidget):
    backClicked = pyqtSignal()
    progressUpdated = pyqtSignal(dict)  # 添加进度更新信号
    
    # 定义布局常量
    FIXED_HEIGHT_TYPE = 0  # 使用固定像素值模式
    LINE_HEIGHT = 200  # 固定行高（像素）
    PARAGRAPH_SPACING = 20  # 段落间距（像素）
    MIN_LINE_HEIGHT_RATIO = 2.5  # 最小行高比例
    MAX_LINE_HEIGHT_RATIO = 4.2  # 最大行高比例
    
    # 字体大小范围
    MIN_FONT_SIZE = 8
    MAX_FONT_SIZE = 48
    
    def __init__(self, parent=None):
        super().__init__(parent)
        
        # 初始化基本属性
        self.current_book = None
        self.chapters = []
        self.current_chapter_index = 0
        self.is_loading = False
        self.scroll_connected = False
        self.is_catalog_visible = True
        self.closing = False
        
        # 加载设置
        self.settings = self.load_settings()
        
        # 初始化面板
        self.settings_panel = None
        self.search_panel = None
        self.is_active = True
        
        # 初始化书签相关属性
        self.bookmarks = []
        self.bookmark_format = QTextCharFormat()
        self.bookmark_format.setUnderlineStyle(QTextCharFormat.UnderlineStyle.WaveUnderline)  # 改为波浪线
        self.bookmark_format.setUnderlineColor(QColor("#4CAF50"))  # 使用更醒目的绿色
        self.bookmark_format.setBackground(QColor(76, 175, 80, 30))  # 添加淡绿色背景
        
        # 创建主布局
        self.main_layout = QVBoxLayout(self)
        self.main_layout.setContentsMargins(0, 0, 0, 0)
        self.main_layout.setSpacing(0)
        
        # 创建工具栏
        self.create_toolbar()
        
        # 创建主分割器
        self.main_splitter = QSplitter(Qt.Orientation.Horizontal)
        self.main_layout.addWidget(self.main_splitter)
        
        # 创建目录树
        self.create_catalog_tree()
        
        # 创建内容区域
        self.create_content_area()
        
        # 创建设置面板
        self.create_settings_panel()  # 在初始化时就创建设置面板
        
        # 初始化定时器
        self.scroll_timer = QTimer()
        self.scroll_timer.setInterval(1000)
        self.scroll_timer.timeout.connect(self.save_current_position)
        
        # 连接滚动信号
        self.scroll_area.verticalScrollBar().valueChanged.connect(self.on_scroll_value_changed)
        
        # 创建右键菜单
        self.create_context_menu()
        
        # 添加快捷键
        self.setup_shortcuts()
        
        # 加载书签数据
        self.load_bookmarks()

    def create_toolbar(self):
        """创建工具栏"""
        toolbar = QWidget()
        toolbar.setFixedHeight(32)
        toolbar.setStyleSheet("background-color: #2B2B2B;")
        
        toolbar_layout = QHBoxLayout(toolbar)
        toolbar_layout.setContentsMargins(10, 0, 10, 0)
        toolbar_layout.setSpacing(8)
        
        # 返回按钮
        back_btn = QPushButton()
        back_btn.setIcon(QIcon("resources/icons/back.svg"))
        back_btn.clicked.connect(self.on_back_clicked)
        back_btn.setFixedSize(32, 32)
        back_btn.setStyleSheet("""
            QPushButton {
                background: transparent;
                border: none;
                border-radius: 4px;
                padding: 0px;
            }
            QPushButton:hover {
                background: rgba(255, 255, 255, 0.1);
            }
        """)
        toolbar_layout.addWidget(back_btn)
        
        # 目录按钮
        self.toggle_catalog_btn = QPushButton()
        self.toggle_catalog_btn.setIcon(QIcon("resources/icons/menu.svg"))
        self.toggle_catalog_btn.clicked.connect(self.toggle_catalog)
        self.toggle_catalog_btn.setFixedSize(32, 32)
        self.toggle_catalog_btn.setStyleSheet(back_btn.styleSheet())
        toolbar_layout.addWidget(self.toggle_catalog_btn)
        
        # 标题标签
        self.title_label = QLabel()
        self.title_label.setStyleSheet("""
            font-size: 16px;
            font-weight: bold;
            color: white;
            padding: 0px 8px;
        """)
        toolbar_layout.addWidget(self.title_label)
        
        # 添加设置按钮
        settings_btn = QPushButton()
        settings_btn.setIcon(QIcon("resources/icons/settings.svg"))
        settings_btn.clicked.connect(self.show_settings_panel)
        settings_btn.setFixedSize(32, 32)
        settings_btn.setStyleSheet(back_btn.styleSheet())
        toolbar_layout.addWidget(settings_btn)
        
        # 创建书签按钮
        self.bookmark_btn = QPushButton()
        self.bookmark_btn.setIcon(QIcon("resources/icons/bookmark.svg"))
        self.bookmark_btn.setToolTip("书签列表")
        self.bookmark_btn.clicked.connect(self.show_bookmark_list)
        self.bookmark_btn.setFixedSize(32, 32)
        self.bookmark_btn.setStyleSheet("""
            QPushButton {
                background: transparent;
                border: none;
                border-radius: 4px;
                padding: 4px;
            }
            QPushButton:hover {
                background: rgba(76, 175, 80, 0.2);
            }
            QPushButton:pressed {
                background: rgba(76, 175, 80, 0.3);
            }
        """)
        toolbar_layout.addWidget(self.bookmark_btn)
        
        toolbar_layout.addStretch()
        self.main_layout.addWidget(toolbar)

    def create_catalog_tree(self):
        """创建目录树"""
        self.catalog_tree = QTreeWidget()
        self.catalog_tree.setHeaderHidden(True)
        self.catalog_tree.setFixedWidth(250)
        self.catalog_tree.itemClicked.connect(self.on_chapter_selected)
        self.catalog_tree.setStyleSheet("""
            QTreeWidget {
                background-color: #2B2B2B;
                border: none;
                color: white;
            }
            QTreeWidget::item {
                padding: 4px;
                border-radius: 4px;
            }
            QTreeWidget::item:selected {
                background-color: #0078D4;
            }
            QTreeWidget::item:hover {
                background-color: rgba(0, 120, 212, 0.5);
            }
        """)
        self.main_splitter.addWidget(self.catalog_tree)

    def create_content_area(self):
        """创建内容区域"""
        content_container = QWidget()
        content_layout = QVBoxLayout(content_container)
        content_layout.setContentsMargins(0, 0, 0, 0)
        content_layout.setSpacing(0)  # 设置间距为0
        
        # 创建滚动区域
        self.scroll_area = QScrollArea()
        self.scroll_area.setWidgetResizable(True)
        self.scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
        self.scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn)
        self.scroll_area.setStyleSheet("""
            QScrollArea {
                border: none;
                background: #1E1E1E;
            }
            QScrollBar:vertical {
                width: 8px;
                background: transparent;
                margin: 0px;
            }
            QScrollBar::handle:vertical {
                background: rgba(255, 255, 255, 0.2);
                min-height: 30px;
                border-radius: 4px;
            }
            QScrollBar::handle:vertical:hover {
                background: rgba(255, 255, 255, 0.3);
            }
            QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
                height: 0px;
            }
            QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
                background: none;
            }
        """)
        
        # 创建内容容器
        self.content_widget = QWidget()
        self.content_widget.setStyleSheet("background: #1E1E1E;")
        content_widget_layout = QVBoxLayout(self.content_widget)
        content_widget_layout.setContentsMargins(20, 20, 20, 20)
        
        # 创建文本编辑器
        self.content_edit = QTextEdit()
        self.content_edit.setReadOnly(True)
        self.content_edit.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
        self.content_edit.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
        self.content_edit.setStyleSheet("""
            QTextEdit {
                background: #1E1E1E;
                color: white;
                border: none;
                selection-background-color: #264F78;
            }
        """)
        
        # 将文本编辑器添加到内容容器
        content_widget_layout.addWidget(self.content_edit)
        
        # 设置滚动区域的内容
        self.scroll_area.setWidget(self.content_widget)
        
        # 将滚动区域添加到主布局
        content_layout.addWidget(self.scroll_area, 1)  # 添加拉伸因子1
        
        # 添加底部导航栏
        nav_bar = QWidget()
        nav_bar.setFixedHeight(28)  # 减小高度到28px，与字体更协调
        nav_bar.setStyleSheet("""
            QWidget {
                background-color: #2B2B2B;
                border-top: 1px solid #3F3F3F;
            }
            QPushButton {
                background: transparent;
                border: 1px solid #4CAF50;
                border-radius: 2px;  /* 更小的圆角 */
                color: #4CAF50;
                padding: 2px 6px;    /* 更小的内边距 */
                min-width: 50px;     /* 更小的最小宽度 */
                font-size: 12px;
                height: 20px;        /* 固定按钮高度 */
            }
            QPushButton:hover {
                background: rgba(76, 175, 80, 0.1);
            }
            QPushButton:disabled {
                border-color: #666666;
                color: #666666;
            }
            QLabel {
                color: white;
                font-size: 12px;
            }
        """)
        
        nav_layout = QHBoxLayout(nav_bar)
        nav_layout.setContentsMargins(8, 0, 8, 0)  # 更小的左右边距
        nav_layout.setSpacing(6)  # 更小的间距
        
        # 上一章按钮
        self.prev_btn = QPushButton("上一章")
        self.prev_btn.clicked.connect(self.show_prev_chapter)
        nav_layout.addWidget(self.prev_btn)
        
        # 章节名称标签
        self.chapter_label = QLabel()
        self.chapter_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        nav_layout.addWidget(self.chapter_label, 1)  # 添加拉伸因子1，使标签占据中间空间
        
        # 下一章按钮
        self.next_btn = QPushButton("下一章")
        self.next_btn.clicked.connect(self.show_next_chapter)
        nav_layout.addWidget(self.next_btn)
        
        # 将导航栏添加到内容布局
        content_layout.addWidget(nav_bar)
        
        # 将内容容器添加到主分割器
        self.main_splitter.addWidget(content_container)

    def create_settings_panel(self):
        """创建设置面板"""
        self.settings_panel = QWidget(self)
        self.settings_panel.setFixedWidth(300)
        self.settings_panel.setStyleSheet("""
            QWidget {
                background: #2B2B2B;
                color: white;
            }
            QLabel {
                color: white;
                font-size: 14px;
            }
            QSlider {
                height: 24px;
            }
            QSlider::groove:horizontal {
                height: 4px;
                background: #555;
                margin: 0px;
                border-radius: 2px;
            }
            QSlider::handle:horizontal {
                background: white;
                width: 16px;
                height: 16px;
                margin: -6px 0;
                border-radius: 8px;
            }
            QSlider::handle:horizontal:hover {
                background: #ccc;
            }
        """)
        
        layout = QVBoxLayout(self.settings_panel)
        layout.setContentsMargins(20, 20, 20, 20)
        layout.setSpacing(16)
        
        # 字体大小设置
        font_size_label = QLabel("字体大小")
        layout.addWidget(font_size_label)
        
        self.font_size_slider = QSlider(Qt.Orientation.Horizontal)
        self.font_size_slider.setMinimum(12)
        self.font_size_slider.setMaximum(32)
        self.font_size_slider.setValue(self.settings['reader'].get('font_size', 16))
        self.font_size_slider.valueChanged.connect(self.on_font_size_changed)
        layout.addWidget(self.font_size_slider)
        
        # 添加当前字体大小显示
        self.font_size_value_label = QLabel(f"当前大小: {self.font_size_slider.value()}")
        layout.addWidget(self.font_size_value_label)
        
        layout.addStretch()
        self.settings_panel.hide()

    def load_book(self, book):
        """加载书籍"""
        try:
            self.is_loading = True
            self.current_book = book
            self.title_label.setText(book.get('title', ''))
            
            # 加载章节内容
            self.load_chapters()
            
            # 恢复上次阅读位置
            last_chapter = book.get('current_chapter', 0)
            last_position = book.get('last_position', 0.0)
            
            # 保存待恢复的位置
            self.pending_position = last_position
            
            # 加载对应章节
            self.load_chapter_content(last_chapter)
            
            print(f"书籍打开完成: {book.get('title', '')}")
            
        except Exception as e:
            print(f"加载书籍失败: {str(e)}")
            self.is_loading = False

    def load_chapters(self):
        """加载书籍章节"""
        try:
            # 清空现有章节
            self.chapters = []
            self.current_chapter_index = 0
            
            # 清空目录树
            self.catalog_tree.clear()
            
            # 读取书籍文件
            if not self.current_book or 'path' not in self.current_book:
                raise ValueError("无效的书籍信息")
                
            book_path = self.current_book['path']
            if not Path(book_path).exists():
                raise FileNotFoundError(f"找不到书籍文件: {book_path}")
            
            # 读取文件内容
            with open(book_path, 'r', encoding='utf-8') as f:
                content = f.read()
            
            # 解析章节
            self.chapters = self.parse_chapters(content)
            
            # 添加章节到目录树
            for i, chapter in enumerate(self.chapters):
                item = QTreeWidgetItem(self.catalog_tree)
                item.setText(0, chapter['title'])
                item.setData(0, Qt.ItemDataRole.UserRole, i)  # 存储章节索引
            
            # 恢复上次阅读的章节
            last_chapter = self.current_book.get('current_chapter', 0)
            if 0 <= last_chapter < len(self.chapters):
                self.current_chapter_index = last_chapter
                # 选中当前章节
                self.catalog_tree.setCurrentItem(
                    self.catalog_tree.topLevelItem(last_chapter)
                )
            
            print(f"加载章节完成: 共{len(self.chapters)}章")
            
        except Exception as e:
            print(f"加载章节失败: {str(e)}")
            # 确保至少有一个空章节
            self.chapters = [{
                'title': '无法加载章节',
                'content': '加载失败: ' + str(e)
            }]

    def parse_chapters(self, content):
        """解析章节内容"""
        try:
            chapters = []
            current_chapter = None
            current_content = []
            
            # 章节标题匹配模式
            chapter_patterns = [
                r'^[（(]?\s*第\s*[0-9零一二三四五六七八九十百千万]+\s*[章节回集卷部篇][)）]?.*$',  # 第X章/节/回/卷/部/篇
                r'^第\s*[0-9零一二三四五六七八九十百千万]+\s*章.*$',  # 第X章 + 任意标题
                r'^[0-9]+[、.]\s*(?=第.*章)',  # 数字编号（必须后接"第...章"）
                r'^第\s*[0-9零一二三四五六七八九十百千万]+\s*[、.\s](?=.*[章节回])',  # 带"第"的数字编号（必须包含章节回等关键字）
                r'^[正序前]\s*文.*$',  # 正文/序文
                r'^[前序]\s*言.*$',  # 前言/序言
                r'^后\s*记.*$',      # 后记
                r'^番\s*外.*$',      # 番外
                r'^[（(]?\s*Chapter\s*[0-9]+\s*[)）]?.*$',  # 英文章节
                r'^引\s*子.*$',      # 引子
                r'^楔\s*子.*$',      # 楔子
                r'^尾\s*声.*$',      # 尾声
                r'^终\s*章.*$',      # 终章
                r'^[0-9]+\s*[.、]\s*第\s*.+\s*章.*$',  # 1. 第一章
                r'^【\s*第\s*[0-9零一二三四五六七八九十百千万]+\s*[章节]\s*】.*$',  # 【第X章】
                r'^「\s*第\s*[0-9零一二三四五六七八九十百千万]+\s*[章节]\s*」.*$',  # 「第X章」
                r'^\s*"\s*第\s*[0-9零一二三四五六七八九十百千万]+\s*[章节]\s*"\s*.*$',   # "第X章"
                r'^［\s*第\s*[0-9零一二三四五六七八九十百千万]+\s*[章节]\s*］.*$',  # ［第X章］
                r'^\[\s*第\s*[0-9零一二三四五六七八九十百千万]+\s*[章节]\s*\].*$',  # [第X章]
                r'^《\s*第\s*[0-9零一二三四五六七八九十百千万]+\s*[章节]\s*》.*$',  # 《第X章》
            ]
            
            def is_chapter_title(line):
                # 1. 如果行文本太长，可能是正文内容而不是标题
                if len(line) > 50:
                    return False
                
                line = line.strip()
                
                # 2. 检查是否匹配标准章节标题模式
                if any(re.match(pattern, line.strip()) for pattern in chapter_patterns):
                    return True
                
                # 3. 检查是否包含正文特征
                # 3.1 检查是否包含对话或描述性语言特征
                if re.search(r'[。，；！？]', line):  # 包含标点符号
                    return False
                    
                # 3.2 检查是否包含条、款、项等非章节序号词
                if re.search(r'第[一二三四五六七八九十百千万0-9]+条', line):
                    return False
                    
                # 3.3 检查是否包含效果、技能等游戏相关词汇
                game_keywords = ['效果', '技能', '伤害', '属性', '装备', '道具', '任务']
                if any(keyword in line for keyword in game_keywords):
                    # 如果是"第X章"格式且包含这些词，仍然视为章节标题
                    if re.match(r'^第\s*[0-9零一二三四五六七八九十百千万]+\s*章\s*.*$', line):
                        return True
                    return False
                
                # 4. 过滤游戏类小说中常见的系统提示和物品信息
                # 4.1 过滤系统提示和物品获得信息
                system_patterns = [
                    r'【叮！.*】',  # 系统提示
                    r'【获得.*】',  # 获得物品
                    r'【.*药剂.*】',  # 药剂物品
                    r'【.*卷轴.*】',  # 卷轴物品
                    r'【.*装备.*】',  # 装备物品
                    r'【.*提示.*】',  # 系统提示
                    r'【.*警告.*】',  # 系统警告
                    r'【.*任务.*】',  # 任务相关
                    r'【.*成就.*】',  # 成就相关
                    r'【.*技能.*】',  # 技能相关
                    r'【.*属性.*】',  # 属性相关
                    r'【.*评价.*】',  # 评价相关
                    r'【.*等级.*】',  # 等级相关
                    r'《.*邀请函》',  # 邀请函
                    r'《.*公告》',    # 公告
                    r'《.*通知》',    # 通知
                ]
                
                # 如果匹配任何系统提示模式，则不是章节标题
                if any(re.match(pattern, line) for pattern in system_patterns):
                    return False
                
                # 4.2 检查是否包含游戏类小说常见的数值和符号
                if re.search(r'[×+\-]?\d+[%％]?', line):  # 包含数值的内容
                    # 如果是"第X章"格式，仍然视为章节标题
                    if re.match(r'^第\s*[0-9零一二三四五六七八九十百千万]+\s*章\s*.*$', line):
                        return True
                    return False
                
                # 5. 如果不是标准章节格式，但可能是特殊章节标题
                # 检查是否以特定字符开始和结束
                special_pairs = [
                    ('【', '】'), ('「', '」'), ('"', '"'), ('［', '］'),
                    ('[', ']'), ('《', '》'), ('(', ')'), ('（', '）')
                ]
                
                for start, end in special_pairs:
                    if line.startswith(start) and line.endswith(end):
                        inner_text = line[len(start):-len(end)].strip()
                        # 特殊章节的内容不应该太长
                        if 2 <= len(inner_text) <= 20:
                            # 检查是否包含常见的章节相关词
                            chapter_keywords = ['章', '节', '回', '卷', '部', '篇', '幕', 
                                             '序', '引子', '楔子', '尾声', '终章']
                            
                            # 5.1 必须包含章节关键词
                            if not any(keyword in inner_text for keyword in chapter_keywords):
                                return False
                                
                            # 5.2 检查是否是标准的章节格式（如：第一章、第1章等）
                            if re.match(r'^第[0-9零一二三四五六七八九十百千万]+[章节回].*$', inner_text):
                                return True
                                
                            # 5.3 检查是否是特殊章节名（如：序章、尾声等）
                            special_chapters = ['序章', '楔子', '引子', '尾声', '终章', '后记']
                            if any(inner_text.startswith(special) for special in special_chapters):
                                return True
                
                return False
            
            lines = content.split('\n')
            seen_chapters = {}  # 用于记录已见过的章节标题及其内容
            
            for line in lines:
                line = line.strip()
                if not line:
                    continue
                    
                if is_chapter_title(line):
                    # 保存前一章节
                    if current_chapter is not None:
                        chapter_content = '\n'.join(current_content)
                        if len(chapter_content.strip()) > 0:  # 只添加有内容的章节
                            # 处理重复章节的逻辑
                            if current_chapter in seen_chapters:
                                # 如果新内容更长，则更新
                                if len(chapter_content) > len(seen_chapters[current_chapter]):
                                    seen_chapters[current_chapter] = chapter_content
                                    # 更新chapters列表中的内容
                                    for ch in chapters:
                                        if ch['title'] == current_chapter:
                                            ch['content'] = chapter_content
                                            break
                            else:
                                chapters.append({
                                    'title': current_chapter,
                                    'content': chapter_content
                                })
                                seen_chapters[current_chapter] = chapter_content
                    
                    current_chapter = line
                    current_content = []
                else:
                    if current_chapter is not None:
                        current_content.append(line)
                    else:
                        # 如果在第一个章节标题之前有内容，创建一个"引言"章节
                        if line.strip():
                            current_chapter = "引言"
                            current_content = [line]
            
            # 处理最后一章
            if current_chapter is not None and current_content:
                chapter_content = '\n'.join(current_content)
                if len(chapter_content.strip()) > 0:
                    if current_chapter in seen_chapters:
                        if len(chapter_content) > len(seen_chapters[current_chapter]):
                            seen_chapters[current_chapter] = chapter_content
                            # 更新chapters列表中的内容
                            for ch in chapters:
                                if ch['title'] == current_chapter:
                                    ch['content'] = chapter_content
                                    break
                    else:
                        chapters.append({
                            'title': current_chapter,
                            'content': chapter_content
                        })
            
            return chapters
        except Exception as e:
            print(f"解析章节时出错: {str(e)}")
            return []

    def update_chapter_tree(self):
        """更新目录树"""
        try:
            self.catalog_tree.clear()
            for i, chapter in enumerate(self.chapters):
                item = QTreeWidgetItem([chapter['title']])
                item.setData(0, Qt.ItemDataRole.UserRole, i)
                self.catalog_tree.addTopLevelItem(item)
                
            # 选中当前章节
            if self.current_book and 'current_chapter' in self.current_book:
                current_index = self.current_book['current_chapter']
                if 0 <= current_index < self.catalog_tree.topLevelItemCount():
                    self.catalog_tree.setCurrentItem(self.catalog_tree.topLevelItem(current_index))
                
        except Exception as e:
            print(f"更新目录树失败: {str(e)}")

    def on_chapter_selected(self, item):
        """章节选择处理"""
        try:
            chapter_index = item.data(0, Qt.ItemDataRole.UserRole)
            if chapter_index is not None:
                self.show_chapter(chapter_index)
        except Exception as e:
            print(f"选择章节失败: {str(e)}")

    def show_chapter(self, index, restore_position=False, search_pos=None):
        """显示章节内容"""
        try:
            if 0 <= index < len(self.chapters):
                # 暂时断开滚动信号
                try:
                    self.scroll_area.verticalScrollBar().valueChanged.disconnect(self.on_scroll_value_changed)
                except:
                    pass
                
                # 加载新内容
                self.load_chapter_content(index)
                
                # 更新阅读进度
                self.current_book['current_chapter'] = index
                
                # 等待内容完全加载后再恢复位置
                def restore_after_load():
                    try:
                        if search_pos is not None:
                            self.highlight_position(search_pos)
                        elif restore_position and 'last_position' in self.current_book:
                            relative_pos = float(self.current_book['last_position'])
                            scrollbar = self.scroll_area.verticalScrollBar()
                            max_scroll = scrollbar.maximum()
                            
                            if max_scroll > 0:
                                new_pos = int(relative_pos * max_scroll)
                                new_pos = max(0, min(new_pos, max_scroll))
                                scrollbar.setValue(new_pos)
                                self.last_scroll_pos = new_pos
                                print(f"恢复阅读位置: {new_pos} (相对位置: {relative_pos:.2%})")
                        
                        # 重新连接滚动信号
                        self.scroll_area.verticalScrollBar().valueChanged.connect(self.on_scroll_value_changed)
                        self.is_active = True
                        
                    except Exception as e:
                        print(f"恢复位置失败: {str(e)}")
                
                # 使用更长的延迟确保内容完全加载
                QTimer.singleShot(1500, restore_after_load)  # 增加延迟时间
                
        except Exception as e:
            print(f"显示章节失败: {str(e)}")

    def on_scroll_value_changed(self, value):
        """滚动条值变化时的处理"""
        try:
            if self.is_loading or not self.current_book:
                return
                
            # 获取当前滚动条位置和最大值
            scrollbar = self.scroll_area.verticalScrollBar()
            max_pos = scrollbar.maximum()
            
            # 计算精确的相对位置(0-1之间的小数)
            relative_pos = value / max_pos if max_pos > 0 else 0
            
            # 更新书籍信息
            self.current_book.update({
                'current_chapter': self.current_chapter_index,
                'last_position': relative_pos,
                'last_read_time': int(time.time())
            })
            
            print(f"滚动位置更新: {relative_pos:.4f} ({value}/{max_pos})")
            
        except Exception as e:
            print(f"处理滚动失败: {str(e)}")

    def save_current_position(self):
        """保存当前阅读位置"""
        try:
            if not self.current_book or not self.content_edit or self.is_loading:
                return
                
            # 获取当前滚动条位置和最大值
            scrollbar = self.scroll_area.verticalScrollBar()
            current_pos = scrollbar.value()
            max_pos = scrollbar.maximum()
            
            if max_pos <= 0:
                return
                
            # 计算精确的相对位置(0-1之间的小数)
            relative_pos = current_pos / max_pos
            
            # 更新书籍信息
            self.current_book.update({
                'current_chapter': self.current_chapter_index,
                'last_position': relative_pos,
                'last_read_time': int(time.time())
            })
            
            # 发送进度更新信号
            self.progressUpdated.emit(self.current_book)
            
            # 保存到文件
            self.save_progress()
            
            print(f"保存阅读位置: 章节{self.current_chapter_index}, "
                  f"位置{relative_pos:.4f} ({current_pos}/{max_pos})")
            
        except Exception as e:
            print(f"保存阅读位置失败: {str(e)}")

    def on_scroll_pressed(self):
        """滚动条按下时的处理"""
        if self.smooth_scroll_timer:
            self.smooth_scroll_timer.stop()
            self.smooth_scroll_timer = None

    def on_scroll_released(self):
        """滚动条释放时的处理"""
        target_pos = self.scroll_area.verticalScrollBar().value()
        self.start_smooth_scroll(target_pos)

    def on_scroll(self, value):
        """处理滚动事件"""
        if self.content_loaded and self.is_active:
            self.update_progress()

    def resizeEvent(self, event):
        """处理窗口大小改变事件"""
        try:
            super().resizeEvent(event)
            # 检查设置面板是否存在且可见
            if hasattr(self, 'settings_panel') and self.settings_panel and self.settings_panel.isVisible():
                # 更新设置面板位置
                self.settings_panel.move(self.width() - self.settings_panel.width(), 0)
                self.settings_panel.setFixedHeight(self.height())
            
            # 检查搜索面板是否存在且可见
            if hasattr(self, 'search_panel') and self.search_panel and self.search_panel.isVisible():
                self.search_panel.setFixedWidth(self.width())
            
            # 更新统计标签位置
            if hasattr(self, 'stats_label'):
                self.update_stats_label_position()
                
        except Exception as e:
            print(f"处理窗口大小改变失败: {str(e)}")

    def update_nav_info(self, stats, total_lines, selected_stats=None, selected_lines=0):
        """更新导航栏信息"""
        try:
            # 构建总体统计信息
            total_info = (
                f"总计：{stats['chinese']}汉字 "
                f"{stats['english']}英文 "
                f"{stats['numbers']}数字 "
                f"{total_lines}行"
            )
            
            # 如果有选中文本，添加选中统计
            if selected_stats and any(selected_stats.values()):
                selected_info = (
                    f" | 选中：{selected_stats['chinese']}汉字 "
                    f"{selected_stats['english']}英文 "
                    f"{selected_stats['numbers']}数字 "
                    f"{selected_lines}行"
                )
                info = total_info + selected_info
            else:
                info = total_info
            
            # 更新导航栏标签
            self.nav_info_label.setText(info)
            
        except Exception as e:
            print(f"更新导航栏信息失败: {str(e)}")

    def on_selection_changed(self):
        """当文本选择变化时更新统计信息"""
        try:
            if not self.content_edit:
                return
            
            cursor = self.content_edit.textCursor()
            if cursor.hasSelection():
                # 获取选中的文本
                selected_text = cursor.selectedText()
                # 计算选中的字数和行数
                selected_stats = self.count_chars(selected_text)
                
                # 计算总体统计
                total_stats = self.count_chars(self.content_edit.toPlainText())
                
                # 更新显示
                self.update_nav_info(total_stats, total_stats['lines'], 
                                   selected_stats, selected_stats['lines'])
            else:
                # 没有选中文本时，只显示总数
                total_stats = self.count_chars(self.content_edit.toPlainText())
                self.update_nav_info(total_stats, total_stats['lines'])
                
        except Exception as e:
            print(f"更新选中文本统计失败: {str(e)}")

    def count_chars(self, text):
        """统计文本中的字符数"""
        try:
            # 统计中文字符
            chinese = len(re.findall(r'[\u4e00-\u9fa5]', text))
            
            # 统计英文字母（连续的字母）
            english_words = re.findall(r'[a-zA-Z]+', text)
            english = sum(len(word) for word in english_words)
            
            # 统计数字（连续的数字）
            number_groups = re.findall(r'\d+', text)
            numbers = sum(len(num) for num in number_groups)
            
            # 统计实际行数（考虑选中文本的换行）
            non_empty_lines = [line for line in text.split('\n') if line.strip()]
            lines = len(non_empty_lines)
            
            return {
                'chinese': chinese,
                'english': english,
                'numbers': numbers,
                'lines': max(lines, 1)  # 至少返回1行
            }
        except Exception as e:
            print(f"统计字符失败: {str(e)}")
            return {'chinese': 0, 'english': 0, 'numbers': 0, 'lines': 0}

    def init_find_panel(self):
        """初始化查找面板"""
        self.search_panel = QWidget(self)
        self.search_panel.setFixedHeight(50)
        self.search_panel.setStyleSheet("""
            QWidget {
                background-color: #2B2B2B;
                border-bottom: 1px solid #404040;
            }
            QLineEdit {
                background-color: #363636;
                border: 1px solid #404040;
                border-radius: 4px;
                color: #E0E0E0;
                padding: 4px 8px;
                min-width: 200px;
            }
            QRadioButton {
                color: #E0E0E0;
                margin: 0 10px;
            }
            QPushButton {
                background-color: transparent;
                color: #E0E0E0;
                border: 1px solid #404040;
                border-radius: 4px;
                padding: 4px 12px;
                min-width: 60px;
            }
            QPushButton:hover {
                background-color: rgba(255, 255, 255, 0.1);
            }
            QPushButton:disabled {
                color: #808080;
                border-color: #303030;
            }
        """)
        
        layout = QHBoxLayout(self.search_panel)
        layout.setContentsMargins(10, 5, 10, 5)
        layout.setSpacing(8)  # 添加间距
        
        # 搜索输入框
        self.search_input = QLineEdit()
        self.search_input.setPlaceholderText("输入搜索内容")
        self.search_input.setFixedWidth(250)  # 固定宽度
        self.search_input.textChanged.connect(self.on_search_text_changed)
        layout.addWidget(self.search_input)
        
        # 搜索范围选择
        scope_widget = QWidget()
        scope_layout = QHBoxLayout(scope_widget)
        scope_layout.setContentsMargins(0, 0, 0, 0)
        scope_layout.setSpacing(5)
        
        self.search_scope_group = QButtonGroup(self)
        
        self.chapter_scope = QRadioButton("当前章节")
        self.chapter_scope.setChecked(True)
        self.book_scope = QRadioButton("全书")
        
        # 添加范围切换的信号连接
        self.chapter_scope.toggled.connect(self.on_search_scope_changed)
        self.book_scope.toggled.connect(self.on_search_scope_changed)
        
        self.search_scope_group.addButton(self.chapter_scope)
        self.search_scope_group.addButton(self.book_scope)
        
        scope_layout.addWidget(self.chapter_scope)
        scope_layout.addWidget(self.book_scope)
        layout.addWidget(scope_widget)
        
        # 添加弹性空间
        layout.addStretch()
        
        # 添加结果计数标签
        self.result_count_label = QLabel()
        self.result_count_label.setStyleSheet("""
            QLabel {
                color: #808080;
                font-size: 12px;
                margin: 0 10px;
            }
        """)
        layout.addWidget(self.result_count_label)
        
        # 上一个/下一个按钮
        nav_widget = QWidget()
        nav_layout = QHBoxLayout(nav_widget)
        nav_layout.setContentsMargins(0, 0, 0, 0)
        nav_layout.setSpacing(5)
        
        self.prev_result_btn = QPushButton("上一个")
        self.prev_result_btn.clicked.connect(self.find_previous)
        self.prev_result_btn.setEnabled(False)
        nav_layout.addWidget(self.prev_result_btn)
        
        self.next_result_btn = QPushButton("下一个")
        self.next_result_btn.clicked.connect(self.find_next)
        self.next_result_btn.setEnabled(False)
        nav_layout.addWidget(self.next_result_btn)
        
        layout.addWidget(nav_widget)
        
        # 关闭按钮
        close_btn = QPushButton("关闭")
        close_btn.clicked.connect(self.hide_find_panel)
        layout.addWidget(close_btn)
        
        # 初始隐藏面板
        self.search_panel.hide()

    def show_find_panel(self):
        """显示/隐藏查找面板"""
        if self.search_panel.isVisible():
            self.hide_find_panel()
        else:
            self.search_panel.show()
            # 调整面板位置和宽度
            self.search_panel.setFixedWidth(self.width())
            self.search_panel.move(0, 32)  # 显示在工具栏下方
            self.search_input.setFocus()
            self.search_input.selectAll()

    def hide_find_panel(self):
        """隐藏查找面板"""
        self.search_panel.hide()
        self.clear_search_results()
        self.scroll_area.setFocus()

    def on_search_text_changed(self, text):
        """搜索文本改变时的处理"""
        try:
            if not text:
                self.match_label.setText("")
                self.clear_search_highlights()
                return
            
            # 获取搜索范围
            is_whole_book = self.search_scope_group.checkedId() == 1
            
            if is_whole_book:
                self.search_in_book(text)
            else:
                self.search_in_chapter(text)
            
        except Exception as e:
            print(f"搜索文本失败: {str(e)}")

    def search_in_chapter(self, text):
        """在当前章节中搜索"""
        try:
            if not text:
                self.match_label.setText("")
                self.clear_search_highlights()
                return
            
            # 保存当前搜索文本
            self.current_search_text = text
            
            # 获取所有匹配位置
            content = self.content_edit.toPlainText()
            matches = list(re.finditer(re.escape(text), content))
            self.current_matches = len(matches)
            
            if self.current_matches > 0:
                # 初始化匹配索引
                self.current_match_index = 0
                
                # 高亮所有匹配项
                self.highlight_matches(text)
                
                # 选中并显示第一个匹配项
                self.select_and_show_match(0)
                
                # 更新匹配计数显示
                self.match_label.setText(f"找到 {self.current_matches} 处匹配 (1/{self.current_matches})")
            else:
                self.match_label.setText("未找到匹配内容")
                self.clear_search_highlights()
            
        except Exception as e:
            print(f"搜索失败: {str(e)}")

    def select_and_show_match(self, index):
        """选中并显示指定索引的匹配项"""
        try:
            # 移动到文档开始
            cursor = self.content_edit.textCursor()
            cursor.movePosition(QTextCursor.MoveOperation.Start)
            self.content_edit.setTextCursor(cursor)
            
            # 查找到指定的匹配项
            for i in range(index + 1):
                self.content_edit.find(self.current_search_text)
            
            # 确保可见
            self.ensure_cursor_visible()
            
        except Exception as e:
            print(f"选中匹配项失败: {str(e)}")

    def search_in_book(self, text):
        """在全书中搜索"""
        try:
            if not text:
                self.match_label.setText("")
                self.clear_search_highlights()
                return
            
            # 保存搜索文本
            self.current_search_text = text
            
            # 保存搜索结果
            self.search_results = {}
            total_matches = 0
            current_chapter_matches = 0
            
            # 先搜索当前章节
            current_matches = self.count_matches_in_text(self.content_edit.toPlainText(), text)
            if current_matches > 0:
                self.search_results[self.current_chapter_index] = current_matches
                total_matches += current_matches
                current_chapter_matches = current_matches
                # 高亮当前章节的匹配项
                self.highlight_matches(text)
            
            # 搜索其他章节
            for i, chapter in enumerate(self.chapters):
                if i != self.current_chapter_index:
                    matches = self.count_matches_in_text(chapter.get('content', ''), text)
                    if matches > 0:
                        self.search_results[i] = matches
                        total_matches += matches
            
            # 初始化全书搜索状态
            self.total_book_matches = total_matches
            self.current_book_match = 1 if current_chapter_matches > 0 else 0
            
            # 显示搜索结果
            if total_matches > 0:
                if current_chapter_matches > 0:
                    self.match_label.setText(f"全书共 {total_matches} 处匹配 (当前章节: 1/{current_chapter_matches})")
                else:
                    self.match_label.setText(f"全书共 {total_matches} 处匹配")
            else:
                self.match_label.setText("未找到匹配内容")
            
        except Exception as e:
            print(f"在全书中搜索失败: {str(e)}")

    def find_next_in_book(self, text):
        """在全书中查找下一个"""
        try:
            if not hasattr(self, 'current_search_text') or text != self.current_search_text:
                self.search_in_book(text)
                return
            
            if not hasattr(self, 'total_book_matches') or self.total_book_matches == 0:
                return
            
            # 在当前章节继续查找
            found = self.content_edit.find(text)
            if found:
                self.current_book_match += 1
                current_chapter_matches = self.search_results.get(self.current_chapter_index, 0)
                current_chapter_match = self.count_matches_before_cursor(text) + 1
                self.match_label.setText(
                    f"全书共 {self.total_book_matches} 处匹配 "
                    f"(当前章节: {current_chapter_match}/{current_chapter_matches})"
                )
                self.ensure_cursor_visible()
                return True
            
            # 在后续章节中查找
            next_chapters = sorted([i for i in self.search_results.keys() if i > self.current_chapter_index])
            if next_chapters:
                next_chapter = next_chapters[0]
                self.load_chapter_content(next_chapter)
                cursor = self.content_edit.textCursor()
                cursor.movePosition(QTextCursor.MoveOperation.Start)
                self.content_edit.setTextCursor(cursor)
                self.find_next_in_book(text)  # 递归调用以找到下一章的第一个匹配
                return True
            
            # 如果已到最后，从头开始
            first_chapter = min(self.search_results.keys())
            if first_chapter != self.current_chapter_index:
                self.load_chapter_content(first_chapter)
                cursor = self.content_edit.textCursor()
                cursor.movePosition(QTextCursor.MoveOperation.Start)
                self.content_edit.setTextCursor(cursor)
                self.find_next_in_book(text)
                return True
            
            return False
            
        except Exception as e:
            print(f"在全书中查找下一个失败: {str(e)}")
            return False

    def count_matches_before_cursor(self, text):
        """计算光标位置之前的匹配数量"""
        try:
            cursor = self.content_edit.textCursor()
            position = cursor.position()
            content = self.content_edit.toPlainText()[:position]
            return len(re.findall(re.escape(text), content))
        except Exception as e:
            print(f"计算光标前匹配数失败: {str(e)}")
            return 0

    def highlight_matches(self, text):
        """高亮所有匹配项"""
        try:
            if not text:
                return
            
            # 保存当前光标位置
            cursor = self.content_edit.textCursor()
            current_position = cursor.position()
            
            # 清除现有高亮
            self.clear_search_highlights()
            
            # 创建高亮格式
            highlight_format = QTextCharFormat()
            highlight_format.setBackground(QColor(255, 255, 0, 100))  # 淡黄色背景
            highlight_format.setForeground(QColor(0, 0, 0))  # 黑色文字
            
            # 从头开始查找并高亮所有匹配项
            cursor = self.content_edit.textCursor()
            cursor.movePosition(QTextCursor.MoveOperation.Start)
            self.content_edit.setTextCursor(cursor)
            
            count = 0
            while self.content_edit.find(text):
                cursor = self.content_edit.textCursor()
                cursor.mergeCharFormat(highlight_format)
                count += 1
            
            # 恢复原来的光标位置
            cursor = self.content_edit.textCursor()
            cursor.setPosition(current_position)
            self.content_edit.setTextCursor(cursor)
            
            # 更新匹配计数显示
            self.match_label.setText(f"找到 {count} 个匹配项")
            
        except Exception as e:
            print(f"高亮匹配项失败: {str(e)}")

    def clear_search_highlights(self):
        """清除所有高亮"""
        try:
            # 创建默认格式
            default_format = QTextCharFormat()
            default_format.setBackground(Qt.GlobalColor.transparent)
            default_format.setForeground(QColor("#FFFFFF"))  # 白色文字
            
            # 应用到整个文档
            cursor = self.content_edit.textCursor()
            cursor.select(QTextCursor.SelectionType.Document)
            cursor.mergeCharFormat(default_format)
            cursor.clearSelection()
            
        except Exception as e:
            print(f"清除高亮失败: {str(e)}")

    def ensure_cursor_visible(self):
        """确保光标位置可见"""
        try:
            # 获取当前光标位置的矩形
            cursor_rect = self.content_edit.cursorRect()
            
            # 将光标位置转换为滚动区域的坐标
            content_pos = self.content_edit.mapTo(self.scroll_area.widget(), cursor_rect.center())
            
            # 获取滚动区域的可见区域
            visible_rect = self.scroll_area.viewport().rect()
            
            # 如果光标不在可见区域内，滚动到光标位置
            if not visible_rect.contains(content_pos):
                # 计算需要滚动的位置，使光标位置位于可见区域的1/3处
                target_y = content_pos.y() - visible_rect.height() / 3
                
                # 设置滚动条位置
                self.scroll_area.verticalScrollBar().setValue(int(target_y))
                
                # 确保滚动完成后光标可见
                QTimer.singleShot(50, lambda: self.scroll_area.ensureVisible(
                    content_pos.x(), content_pos.y(),
                    0, int(visible_rect.height() / 3)
                ))
        
        except Exception as e:
            print(f"确保光标可见失败: {str(e)}")

    def on_search_scope_changed(self):
        """搜索范围改变时的处理"""
        try:
            text = self.search_input.text()
            if text:  # 只有在有搜索文本时才重新搜索
                if self.search_scope_group.checkedId() == 0:
                    self.search_in_chapter(text)
                else:
                    self.search_in_book(text)
                    # 立即执行一次查找，确保显示第一个结果
                    self.find_next_in_book(text)
        except Exception as e:
            print(f"切换搜索范围失败: {str(e)}")

    def process_text_for_display(self, content):
        """处理文本用于显示，处理换行和引号"""
        try:
            # 按原有的换行符分割段落
            paragraphs = content.split('\n')
            result = []
            
            for para in paragraphs:
                if para.strip():
                    # 保持段落完整性
                    result.append(para.strip())
            
            return '\n'.join(result)
            
        except Exception as e:
            print(f"处理文本失败: {str(e)}")
            return content

    def process_quoted_text(self, content):
        """处理文本中的引号内容，使用零宽不换行空格来防止换行"""
        import re
        
        def process_chunk(text):
            """分块处理文本，避免处理过大的文本导致性能问题"""
            # 使用非贪婪模式匹配最近的引号对，包括引号在内的整体
            pattern = r'([""]((?:[^""]|[""][^""])*?)[""])'
            
            def replace_quotes(match):
                # 获取整个引号内容（包括引号）
                full_text = match.group(1)
                # 将整个引号内容（包括引号）用零宽不换行空格连接
                return '\u2060'.join(full_text)
            
            try:
                return re.sub(pattern, replace_quotes, text)
            except Exception as e:
                print(f"处理文本块失败: {str(e)}")
                return text
        
        try:
            # 分块处理大文本
            chunk_size = 10000  # 每次处理10000个字符
            chunks = [content[i:i+chunk_size] for i in range(0, len(content), chunk_size)]
            
            processed_chunks = []
            
            # 确保不会在引号内容中间分块
            current_chunk = ''
            in_quotes = False
            
            for chunk in chunks:
                current_chunk += chunk
                
                # 处理当前块
                if not in_quotes:
                    # 检查是否有未闭合的引号
                    quote_count = sum(1 for c in current_chunk if c in '""')
                    if quote_count % 2 == 0:
                        # 引号都是成对的，可以安全处理
                        processed = process_chunk(current_chunk)
                        processed_chunks.append(processed)
                        current_chunk = ''
                    else:
                        # 有未闭合的引号，需要等待下一块
                        in_quotes = True
                        continue
                else:
                    # 在引号内，查找闭合引号
                    quote_count = sum(1 for c in current_chunk if c in '""')
                    if quote_count % 2 == 0:
                        # 找到闭合引号，可以处理
                        in_quotes = False
                        processed = process_chunk(current_chunk)
                        processed_chunks.append(processed)
                        current_chunk = ''
            
            # 处理剩余内容
            if current_chunk:
                processed = process_chunk(current_chunk)
                processed_chunks.append(processed)
            
            return ''.join(processed_chunks)
            
        except Exception as e:
            print(f"处理引号内容失败: {str(e)}")
            return content

    def split_content_with_quotes(self, content):
        """分割文本，保持引号内容完整"""
        try:
            result = []
            lines = content.split('\n')
            
            for line in lines:
                if not line.strip():
                    continue
                    
                # 分析当前行
                parts = []
                current = ''
                in_quote = False
                quote_start = -1
                
                # 逐字符分析
                for j, char in enumerate(line):
                    if char == '"':
                        if not in_quote:
                            # 开始引号
                            if current:
                                parts.append((current, False))
                                current = ''
                            quote_start = j
                            in_quote = True
                        else:
                            # 结束引号
                            quote_text = line[quote_start:j+1]
                            parts.append((quote_text, True))
                            current = ''
                            in_quote = False
                            continue
                    
                    if in_quote:
                        continue
                    else:
                        current += char
                
                # 处理剩余文本
                if current:
                    parts.append((current, False))
                
                # 将当前行的部分添加到结果中
                result.extend(parts)
            
            return result
            
        except Exception as e:
            print(f"分割文本失败: {str(e)}")
            return [(content, False)]

    def update_progress(self):
        """更新阅读进度"""
        if not self.current_book or not self.is_active:
            return
        
        try:
            # 获取当前状态
            current_chapter = self.current_book['current_chapter']
            scrollbar = self.scroll_area.verticalScrollBar()
            current_pos = scrollbar.value()
            max_scroll = scrollbar.maximum()
            
            # 计算相对位置
            relative_pos = current_pos / max_scroll if max_scroll > 0 else 0
            
            # 更新书籍数据
            self.current_book['progress'] = int((current_chapter + 1) / len(self.chapters) * 100)
            
            # 立即保存到文件
            self.save_progress()
            
            print(f"更新阅读进度: 章节 {current_chapter + 1}/{len(self.chapters)}, "
                  f"位置 {relative_pos:.2%}")
            
        except Exception as e:
            print(f"更新进度失败: {str(e)}")

    def upload_cover(self):
        """上传封面图片"""
        file_name, _ = QFileDialog.getOpenFileName(
            self,
            "选择封面图片",
            "",
            "图片文件 (*.jpg *.jpeg *.png *.bmp)"
        )
        if file_name:
            # 更新书籍数据中的封面路径
            self.current_book['cover'] = file_name
            
            # 显示新封面
            pixmap = QPixmap(file_name)
            if not pixmap.isNull():
                # 使用统一的封面尺寸
                scaled_pixmap = pixmap.scaled(
                    144, 180,  # 使用与 BookCard 相同的尺寸
                    Qt.AspectRatioMode.IgnoreAspectRatio,
                    Qt.TransformationMode.SmoothTransformation
                )
                self.cover_label.setPixmap(scaled_pixmap)
            
            print(f"设置封面图片: {file_name}") 

    def update_nav_buttons(self):
        """更新导航按钮状态"""
        try:
            if not self.current_book or 'current_chapter' not in self.current_book:
                self.prev_btn.setEnabled(False)
                self.next_btn.setEnabled(False)
                return
            
            current_chapter = self.current_book['current_chapter']
            total_chapters = len(self.chapters)
            
            # 更新按钮状态
            self.prev_btn.setEnabled(current_chapter > 0)
            self.next_btn.setEnabled(current_chapter < total_chapters - 1)
            
            # 更新按钮提示文本
            if current_chapter > 0:
                self.prev_btn.setToolTip(f"上一章：{self.chapters[current_chapter - 1]['title']}")
            if current_chapter < total_chapters - 1:
                self.next_btn.setToolTip(f"下一章：{self.chapters[current_chapter + 1]['title']}")
            
        except Exception as e:
            print(f"更新导航按钮状态失败: {str(e)}")

    def show_prev_chapter(self):
        """显示上一章"""
        try:
            if self.current_book and 'current_chapter' in self.current_book:
                current_chapter = self.current_book['current_chapter']
                if current_chapter > 0:
                    # 保存当前章节的阅读状态
                    self.save_reading_state()
                    # 显示上一章，不恢复位置（从头开始）
                    self.show_chapter(current_chapter - 1, restore_position=False)
                    # 更新导航按钮状态
                    self.update_nav_buttons()
                
        except Exception as e:
            print(f"显示上一章失败: {str(e)}")

    def show_next_chapter(self):
        """显示下一章"""
        try:
            if self.current_book and 'current_chapter' in self.current_book:
                current_chapter = self.current_book['current_chapter']
                if current_chapter < len(self.chapters) - 1:
                    # 保存当前章节的阅读状态
                    self.save_reading_state()
                    # 显示下一章，不恢复位置（从头开始）
                    self.show_chapter(current_chapter + 1, restore_position=False)
                    # 更新导航按钮状态
                    self.update_nav_buttons()
                
        except Exception as e:
            print(f"显示下一章失败: {str(e)}")

    def closeEvent(self, event):
        """窗口关闭时保存阅读位置"""
        if not self.closing:
            self.closing = True
            self.save_reading_state()
            self.stop_progress_update()  # 停止进度更新
        event.accept()
        
    def save_reading_state(self):
        """保存当前阅读状态（仅在退出时调用）"""
        try:
            if self.current_book and self.is_active:
                scrollbar = self.scroll_area.verticalScrollBar()
                max_scroll = scrollbar.maximum()
                current_pos = scrollbar.value()
                
                if max_scroll > 0:
                    relative_pos = current_pos / max_scroll
                    self.current_book['last_position'] = relative_pos
                    self.save_progress()
                    print(f"退出时保存阅读状态: 章节 {self.current_book['current_chapter']}, 位置 {relative_pos:.2%}")
            
        except Exception as e:
            print(f"保存阅读状态失败: {str(e)}")

    def on_back_clicked(self):
        """返回按钮点击处理"""
        try:
            # 保存当前阅读位置
            self.save_current_position()
            
            # 停止定时器
            if self.scroll_timer.isActive():
                self.scroll_timer.stop()
            
            # 发送返回信号
            self.backClicked.emit()
            
        except Exception as e:
            print(f"返回处理失败: {str(e)}")

    def stop_progress_update(self):
        """停止进度更新"""
        try:
            self.is_active = False
            if self.update_timer:
                self.update_timer.stop()
                self.update_timer = None
            print("停止进度更新")
        except Exception as e:
            print(f"停止进度更新失败: {str(e)}")

    def update_statistics(self):
        """更新统计信息"""
        try:
            if not self.content_edit:
                return
            
            # 获取文本内容
            text = self.content_edit.toPlainText()
            
            # 统计字符
            stats = self.count_chars(text)
            
            # 更新导航栏信息
            self.update_nav_info(stats, stats['lines'])
            
        except Exception as e:
            print(f"更新统计信息失败: {str(e)}")

    def update_stats_label_position(self):
        """更新统计标签位置"""
        try:
            if hasattr(self, 'stats_label'):
                # 获取滚动区域的大小
                scroll_area_rect = self.scroll_area.geometry()
                
                # 计算标签位置（右下角，留出一定边距）
                margin = 20
                x = scroll_area_rect.right() - self.stats_label.width() - margin
                y = scroll_area_rect.bottom() - self.stats_label.height() - margin
                
                # 设置标签位置
                self.stats_label.move(x, y)
                
                # 确保标签始终显示
                self.stats_label.raise_()
                self.stats_label.show()
                
        except Exception as e:
            print(f"更新统计标签位置失败: {str(e)}")

    def load_settings(self):
        """加载设置"""
        try:
            settings_file = Path("settings.json")
            if settings_file.exists():
                with open(settings_file, 'r', encoding='utf-8') as f:
                    return json.load(f)
            return {
                "reader": {
                    "font_size": 16,
                    "line_spacing": 1.5,
                    "line_height": 500,
                    "theme": "深色主题",
                    "font_family": "Microsoft YaHei",
                    "save_position_interval": 1000
                }
            }
        except Exception as e:
            print(f"加载设置失败: {str(e)}")
            return {
                "reader": {
                    "font_size": 16,
                    "line_spacing": 1.5,
                    "line_height": 500,
                    "theme": "深色主题",
                    "font_family": "Microsoft YaHei",
                    "save_position_interval": 1000
                }
            }

    def update_catalog_tooltip(self):
        """更新目录按钮的提示文本"""
        try:
            if self.is_catalog_visible:
                self.toggle_catalog_btn.setToolTip("隐藏目录")
            else:
                self.toggle_catalog_btn.setToolTip("显示目录")
        except Exception as e:
            print(f"更新目录按钮提示失败: {str(e)}")

    def toggle_catalog(self):
        """切换目录显示状态"""
        try:
            # 切换目录可见性
            self.is_catalog_visible = not self.is_catalog_visible
            
            # 更新目录树的可见性
            if self.is_catalog_visible:
                self.catalog_tree.show()
                self.main_splitter.setSizes([250, self.width() - 250])  # 显示目录时设置宽度
            else:
                self.catalog_tree.hide()
                self.main_splitter.setSizes([0, self.width()])  # 隐藏目录时将宽度设为0
            
            # 更新按钮提示文本
            self.update_catalog_tooltip()
            
        except Exception as e:
            print(f"切换目录显示失败: {str(e)}")

    def show_settings_panel(self):
        """显示/隐藏设置面板"""
        try:
            if self.settings_panel.isVisible():
                self.settings_panel.hide()
            else:
                # 设置面板位置（右侧）
                self.settings_panel.move(self.width() - self.settings_panel.width(), 0)
                self.settings_panel.setFixedHeight(self.height())
                self.settings_panel.show()
                
                # 更新设置控件的值
                self.font_size_slider.setValue(self.settings['reader'].get('font_size', 16))
                self.font_size_value_label.setText(f"当前大小: {self.font_size_slider.value()}")
                
        except Exception as e:
            print(f"显示设置面板失败: {str(e)}")

    def on_font_size_changed(self, value):
        """字体大小改变时的处理"""
        try:
            # 更新设置
            self.settings['reader']['font_size'] = value
            
            # 更新显示的值
            if hasattr(self, 'font_size_value_label'):
                self.font_size_value_label.setText(f"当前大小: {value}")
            
            # 保存设置
            self.save_settings()
            
            # 重新加载当前章节
            if self.current_book and hasattr(self, 'current_chapter_index'):
                # 保存当前滚动位置
                scrollbar = self.scroll_area.verticalScrollBar()
                relative_pos = scrollbar.value() / scrollbar.maximum() if scrollbar.maximum() > 0 else 0
                
                # 重新加载内容
                self.load_chapter_content(self.current_chapter_index)
                
                # 恢复滚动位置
                self.pending_position = relative_pos
            
        except Exception as e:
            print(f"更新字体大小失败: {str(e)}")

    def save_settings(self):
        """保存设置到文件"""
        try:
            settings_file = Path("settings.json")
            with open(settings_file, 'w', encoding='utf-8') as f:
                json.dump(self.settings, f, ensure_ascii=False, indent=2)
            print(f"保存设置成功: 字体大小 {self.settings['reader']['font_size']}")
            
        except Exception as e:
            print(f"保存设置失败: {str(e)}")

    def load_chapter_content(self, chapter_index):
        """加载章节内容"""
        try:
            if not self.chapters or chapter_index >= len(self.chapters):
                return
                
            # 暂停滚动监听
            self.is_loading = True
            self.current_chapter_index = chapter_index
            
            # 获取章节内容
            chapter = self.chapters[chapter_index]
            
            # 清除现有内容
            self.content_edit.clear()
            
            # 设置基本字体
            font_size = self.settings['reader'].get('font_size', 16)
            base_font = QFont("Microsoft YaHei", font_size)
            self.content_edit.setFont(base_font)
            
            # 插入内容
            self.insert_chapter_content(chapter, font_size)
            
            # 等待内容渲染完成
            QTimer.singleShot(100, lambda: self.finish_loading(chapter))
            
            # 切换章节时滚动到顶部
            self.scroll_area.verticalScrollBar().setValue(0)
            
            # 更新章节标题
            self.chapter_label.setText(chapter['title'])
            
            # 更新导航按钮状态
            self.prev_btn.setEnabled(chapter_index > 0)
            self.next_btn.setEnabled(chapter_index < len(self.chapters) - 1)
            
            # 添加按钮提示文本
            if chapter_index > 0:
                self.prev_btn.setToolTip(f"上一章：{self.chapters[chapter_index - 1]['title']}")
            if chapter_index < len(self.chapters) - 1:
                self.next_btn.setToolTip(f"下一章：{self.chapters[chapter_index + 1]['title']}")
            
        except Exception as e:
            print(f"加载章节内容失败: {str(e)}")
            self.is_loading = False

    def insert_chapter_content(self, chapter, font_size):
        """插入章节内容"""
        try:
            # 清除现有内容
            self.content_edit.clear()
            
            # 创建文档
            doc = QTextDocument()
            doc.setDefaultFont(QFont("Microsoft YaHei", font_size))
            
            # 设置文档样式
            doc.setDefaultStyleSheet("""
                body { color: white; }
                .title { 
                    font-size: %dpt; 
                    font-weight: bold;
                    text-align: center;
                    margin-bottom: 20px;
                }
                .content {
                    text-indent: %dpx;
                    line-height: 1.8;
                    margin-bottom: 8px;
                }
            """ % (font_size + 4, font_size * 2))
            
            # 构建HTML内容
            html_content = f"""
                <div class="title">{chapter.get('title', '')}</div>
            """
            
            # 处理段落
            paragraphs = chapter.get('content', '').split('\n')
            for paragraph in paragraphs:
                if paragraph.strip():
                    html_content += f'<div class="content">{paragraph.strip()}</div>'
            
            # 设置文档内容
            doc.setHtml(html_content)
            
            # 设置文档到编辑器
            self.content_edit.setDocument(doc)
            
            # 强制更新布局
            self.content_edit.document().setTextWidth(self.content_edit.viewport().width())
            
            # 计算文档高度并转换为整数
            doc_height = int(round(self.content_edit.document().size().height()))
            self.content_widget.setMinimumHeight(doc_height)
            
            print(f"内容插入完成: {len(paragraphs)} 段, 文档高度: {doc_height}")
            
        except Exception as e:
            print(f"插入章节内容失败: {str(e)}")

    def finish_loading(self, chapter):
        """完成加载处理"""
        try:
            # 等待布局完成
            QApplication.processEvents()
            
            # 确保内容已经渲染
            self.content_edit.document().setTextWidth(self.content_edit.viewport().width())
            
            # 计算高度并转换为整数
            doc_height = int(round(self.content_edit.document().size().height()))
            self.content_widget.setMinimumHeight(doc_height)
            
            # 恢复滚动监听
            self.is_loading = False
            
            # 如果有待恢复的位置，现在恢复
            if hasattr(self, 'pending_position'):
                relative_pos = self.pending_position
                delattr(self, 'pending_position')
                # 使用短延迟确保布局完成
                QTimer.singleShot(100, lambda: self.restore_exact_position(relative_pos))
            
            print(f"章节加载完成: {chapter['title']}, 文档高度: {doc_height}")
            
        except Exception as e:
            print(f"完成加载处理失败: {str(e)}")
            self.is_loading = False

    def restore_exact_position(self, relative_pos, retry_count=0):
        """恢复精确的阅读位置"""
        try:
            if self.is_loading:
                self.pending_position = relative_pos
                return
                
            scrollbar = self.scroll_area.verticalScrollBar()
            max_pos = scrollbar.maximum()
            
            # 添加最大重试次数限制
            MAX_RETRIES = 5
            if max_pos <= 0:
                if retry_count >= MAX_RETRIES:
                    print(f"加载超时: 已重试{retry_count}次，停止重试")
                    return
                    
            print(f"滚动条最大值为0，等待内容加载... (relative_pos: {relative_pos}, 重试次数: {retry_count + 1}/{MAX_RETRIES})")
            # 强制更新布局
            self.content_edit.document().setTextWidth(self.content_edit.viewport().width())
            doc_height = int(round(self.content_edit.document().size().height()))
            self.content_widget.setMinimumHeight(doc_height)
            QApplication.processEvents()
            
            # 重新获取最大值
            max_pos = scrollbar.maximum()
            if max_pos <= 0:
                # 增加重试间隔时间，避免过于频繁的重试
                delay = 200 * (retry_count + 1)  # 递增延迟时间
                QTimer.singleShot(delay, lambda: self.restore_exact_position(relative_pos, retry_count + 1))
                return
            
            # 计算精确的滚动位置
            target_pos = int(relative_pos * max_pos)
            
            # 设置滚动位置
            scrollbar.setValue(target_pos)
            
            print(f"恢复到位置: {relative_pos:.4f} -> {target_pos} (最大值: {max_pos})")
            
        except Exception as e:
            print(f"恢复阅读位置失败: {str(e)}")
            self.is_loading = False

    def save_progress(self):
        """保存进度到文件"""
        try:
            if not self.current_book:
                return
            
            # 读取现有的书架数据
            data_dir = Path("data")
            bookshelf_file = data_dir / "bookshelf.json"
            
            if bookshelf_file.exists():
                with open(bookshelf_file, 'r', encoding='utf-8') as f:
                    data = json.load(f)
                
                # 更新书籍信息
                for book in data['books']:
                    if book['id'] == self.current_book['id']:
                        # 确保保存的是浮点数
                        book['last_position'] = float(self.current_book['last_position'])
                        book['current_chapter'] = self.current_book['current_chapter']
                        book['progress'] = self.current_book['progress']
                        break
                
                # 保存更新后的数据
                with open(bookshelf_file, 'w', encoding='utf-8') as f:
                    json.dump(data, f, ensure_ascii=False, indent=2)
                    
                print(f"保存进度成功: 章节 {self.current_book['current_chapter']}, "
                      f"位置 {self.current_book['last_position']:.2%}")
                    
        except Exception as e:
            print(f"保存进度失败: {str(e)}")

    def create_context_menu(self):
        """创建右键菜单"""
        self.content_edit.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
        self.content_edit.customContextMenuRequested.connect(self.show_context_menu)

    def show_context_menu(self, pos):
        """显示右键菜单"""
        try:
            menu = self.content_edit.createStandardContextMenu()
            cursor = self.content_edit.textCursor()
            
            # 如果有选中文本，添加书签选项
            if cursor.hasSelection():
                menu.addSeparator()
                add_bookmark = menu.addAction("添加书签")
                add_bookmark.triggered.connect(self.add_bookmark)
            
            # 显示菜单
            menu.exec(self.content_edit.mapToGlobal(pos))
            
        except Exception as e:
            print(f"显示右键菜单失败: {str(e)}")

    def setup_shortcuts(self):
        """设置快捷键"""
        try:
            # 查找快捷键
            find_shortcut = QShortcut(QKeySequence("Ctrl+F"), self)
            find_shortcut.activated.connect(self.show_search_panel)
            
        except Exception as e:
            print(f"设置快捷键失败: {str(e)}")

    def create_search_panel(self):
        """创建搜索面板"""
        try:
            # 创建搜索面板
            self.search_panel = QFrame(self)
            self.search_panel.setObjectName("searchPanel")
            self.search_panel.setStyleSheet("""
                QFrame#searchPanel {
                    background-color: #2B2B2B;
                    border-bottom: 1px solid #3F3F3F;
                }
                QPushButton {
                    background: transparent;
                    border: 1px solid #3F3F3F;
                    border-radius: 4px;
                    color: white;
                    padding: 4px 8px;
                }
                QPushButton:hover {
                    background-color: rgba(255, 255, 255, 0.1);
                }
                QLineEdit {
                    background: rgba(255, 255, 255, 0.1);
                    border: 1px solid #3F3F3F;
                    border-radius: 4px;
                    color: white;
                    padding: 4px 8px;
                }
                QRadioButton {
                    color: white;
                }
                QLabel {
                    color: rgba(255, 255, 255, 0.7);
                }
            """)
            
            # 创建水平布局
            layout = QHBoxLayout(self.search_panel)
            layout.setContentsMargins(10, 5, 10, 5)
            layout.setSpacing(8)
            
            # 搜索输入框
            self.search_input = QLineEdit()
            self.search_input.setPlaceholderText("输入搜索内容")
            self.search_input.setFixedWidth(200)
            self.search_input.textChanged.connect(self.on_search_text_changed)
            layout.addWidget(self.search_input)
            
            # 上一个/下一个按钮
            prev_btn = QPushButton("上一个")
            prev_btn.clicked.connect(lambda: self.find_previous(self.search_input.text()))
            next_btn = QPushButton("下一个")
            next_btn.clicked.connect(lambda: self.find_next(self.search_input.text()))
            layout.addWidget(prev_btn)
            layout.addWidget(next_btn)
            
            # 搜索范围选择
            scope_layout = QHBoxLayout()
            self.search_scope_group = QButtonGroup(self)
            
            chapter_radio = QRadioButton("当前章节")
            chapter_radio.setChecked(True)
            self.search_scope_group.addButton(chapter_radio, 0)
            scope_layout.addWidget(chapter_radio)
            
            book_radio = QRadioButton("全书")
            self.search_scope_group.addButton(book_radio, 1)
            
            scope_layout.addWidget(book_radio)
            
            # 连接范围改变信号
            self.search_scope_group.buttonClicked.connect(self.on_search_scope_changed)
            
            layout.addLayout(scope_layout)
            
            # 匹配计数标签
            self.match_label = QLabel()
            layout.addWidget(self.match_label)
            
            # 关闭按钮
            close_btn = QPushButton("×")
            close_btn.setFixedSize(24, 24)
            close_btn.clicked.connect(self.hide_search_panel)
            layout.addWidget(close_btn)
            
            # 添加伸缩项
            layout.addStretch()
            
            # 设置固定高度
            self.search_panel.setFixedHeight(40)
            
            # 默认隐藏
            self.search_panel.hide()
            
            print("搜索面板创建成功")
            
        except Exception as e:
            print(f"创建搜索面板失败: {str(e)}")

    def show_search_panel(self):
        """显示搜索面板"""
        try:
            # 如果面板不存在，创建它
            if not hasattr(self, 'search_panel') or not self.search_panel:
                self.create_search_panel()
            
            # 更新面板宽度以匹配父窗口
            self.search_panel.setFixedWidth(self.width())
            
            # 显示面板
            self.search_panel.show()
            self.search_panel.raise_()
            
            # 聚焦到搜索输入框
            self.search_input.setFocus()
            self.search_input.selectAll()
            
            print("搜索面板显示成功")
            
        except Exception as e:
            print(f"显示搜索面板失败: {str(e)}")

    def hide_search_panel(self):
        """隐藏搜索面板"""
        try:
            if hasattr(self, 'search_panel'):
                self.search_panel.hide()
                self.clear_search_highlights()
            
        except Exception as e:
            print(f"隐藏搜索面板失败: {str(e)}")

    def on_search_text_changed(self, text):
        """搜索文本改变时的处理"""
        try:
            if not text:
                self.match_label.setText("")
                self.clear_search_highlights()
                return
            
            # 获取搜索范围
            is_whole_book = self.search_scope_group.checkedId() == 1
            
            if is_whole_book:
                self.search_in_book(text)
            else:
                self.search_in_chapter(text)
            
        except Exception as e:
            print(f"搜索文本失败: {str(e)}")

    def find_next(self, text):
        """查找下一个匹配项"""
        try:
            # 获取搜索范围
            is_whole_book = self.search_scope_group.checkedId() == 1
            
            if is_whole_book:
                self.find_next_in_book(text)
            else:
                self.find_next_in_chapter(text)
            
        except Exception as e:
            print(f"查找下一个失败: {str(e)}")

    def find_previous(self, text):
        """查找上一个匹配项"""
        try:
            # 获取搜索范围
            is_whole_book = self.search_scope_group.checkedId() == 1
            
            if is_whole_book:
                self.find_previous_in_book(text)
            else:
                self.find_previous_in_chapter(text)
            
        except Exception as e:
            print(f"查找上一个失败: {str(e)}")

    def find_next_in_chapter(self, text):
        """在当前章节中查找下一个"""
        try:
            if not text:
                return False
            
            # 查找下一个匹配项
            found = self.content_edit.find(text)
            
            if found:
                # 重新高亮所有匹配项
                self.highlight_matches(text)
                # 确保找到的位置可见
                self.ensure_cursor_visible()
                return True
            
            # 如果没找到，从头开始查找
            cursor = self.content_edit.textCursor()
            cursor.movePosition(QTextCursor.MoveOperation.Start)
            self.content_edit.setTextCursor(cursor)
            
            found = self.content_edit.find(text)
            if found:
                self.highlight_matches(text)
                self.ensure_cursor_visible()
                return True
            
            return False
            
        except Exception as e:
            print(f"查找下一个失败: {str(e)}")
            return False

    def find_previous_in_chapter(self, text):
        """在当前章节中查找上一个"""
        try:
            if not text:
                return False
            
            # 查找上一个匹配项
            found = self.content_edit.find(text, QTextDocument.FindFlag.FindBackward)
            
            if found:
                # 重新高亮所有匹配项
                self.highlight_matches(text)
                # 确保找到的位置可见
                self.ensure_cursor_visible()
                return True
            
            # 如果没找到，从末尾开始查找
            cursor = self.content_edit.textCursor()
            cursor.movePosition(QTextCursor.MoveOperation.End)
            self.content_edit.setTextCursor(cursor)
            
            found = self.content_edit.find(text, QTextDocument.FindFlag.FindBackward)
            if found:
                self.highlight_matches(text)
                self.ensure_cursor_visible()
                return True
            
            return False
            
        except Exception as e:
            print(f"查找上一个失败: {str(e)}")
            return False

    def count_matches_in_text(self, text, pattern):
        """统计文本中的匹配数量"""
        try:
            if not text or not pattern:
                return 0
            
            # 使用正则表达式查找所有匹配项
            matches = re.finditer(re.escape(pattern), text)
            count = len(list(matches))
            
            return count
            
        except Exception as e:
            print(f"统计匹配数量失败: {str(e)}")
            return 0

    def find_previous_in_book(self, text):
        """在全书中查找上一个"""
        try:
            if not hasattr(self, 'current_search_text') or text != self.current_search_text:
                self.search_in_book(text)
                return
            
            if not hasattr(self, 'total_book_matches') or self.total_book_matches == 0:
                return
            
            # 在当前章节查找上一个
            found = self.content_edit.find(text, QTextDocument.FindFlag.FindBackward)
            if found:
                current_chapter_matches = self.search_results.get(self.current_chapter_index, 0)
                current_chapter_match = self.count_matches_before_cursor(text)
                self.match_label.setText(
                    f"全书共 {self.total_book_matches} 处匹配 "
                    f"(当前章节: {current_chapter_match}/{current_chapter_matches})"
                )
                self.ensure_cursor_visible()
                return True
            
            # 在前面的章节中查找
            prev_chapters = sorted([i for i in self.search_results.keys() if i < self.current_chapter_index], 
                                 reverse=True)
            if prev_chapters:
                prev_chapter = prev_chapters[0]
                self.load_chapter_content(prev_chapter)
                cursor = self.content_edit.textCursor()
                cursor.movePosition(QTextCursor.MoveOperation.End)
                self.content_edit.setTextCursor(cursor)
                self.find_previous_in_book(text)  # 递归调用以找到上一章的最后一个匹配
                return True
            
            # 如果已到开头，从末尾开始
            last_chapter = max(self.search_results.keys())
            if last_chapter != self.current_chapter_index:
                self.load_chapter_content(last_chapter)
                cursor = self.content_edit.textCursor()
                cursor.movePosition(QTextCursor.MoveOperation.End)
                self.content_edit.setTextCursor(cursor)
                self.find_previous_in_book(text)
                return True
            
            return False
            
        except Exception as e:
            print(f"在全书中查找上一个失败: {str(e)}")
            return False

    def add_bookmark(self):
        """添加书签"""
        try:
            cursor = self.content_edit.textCursor()
            if not cursor.hasSelection():
                return
            
            # 获取选中的文本和位置
            selected_text = cursor.selectedText()
            start_pos = cursor.selectionStart()
            end_pos = cursor.selectionEnd()
            
            # 弹出输入对话框
            name, ok = QInputDialog.getText(
                self,
                "添加书签",
                "请输入书签名称:",
                QLineEdit.EchoMode.Normal,
                selected_text[:20] + "..." if len(selected_text) > 20 else selected_text
            )
            
            if ok and name:
                # 创建书签数据
                bookmark = {
                    'id': str(uuid.uuid4()),
                    'name': name,
                    'text': selected_text,
                    'start_pos': start_pos,
                    'end_pos': end_pos,
                    'chapter_index': self.current_chapter_index,
                    'create_time': time.strftime('%Y-%m-%d %H:%M:%S')
                }
                
                # 添加书签
                self.bookmarks.append(bookmark)
                
                # 应用书签格式
                self.apply_bookmark_format(start_pos, end_pos)
                
                # 保存书签
                self.save_bookmarks()
                
            QMessageBox.information(self, "成功", "书签添加成功！")
            
        except Exception as e:
            print(f"添加书签失败: {str(e)}")
            QMessageBox.warning(self, "错误", f"添加书签失败: {str(e)}")

    def apply_bookmark_format(self, start_pos, end_pos):
        """应用书签格式"""
        try:
            cursor = QTextCursor(self.content_edit.document())
            cursor.setPosition(start_pos)
            cursor.setPosition(end_pos, QTextCursor.MoveMode.KeepAnchor)
            cursor.mergeCharFormat(self.bookmark_format)
        except Exception as e:
            print(f"应用书签格式失败: {str(e)}")

    def show_bookmark_list(self):
        """显示书签列表"""
        try:
            if not self.bookmarks:
                QMessageBox.information(self, "提示", "当前没有书签")
                return
            
            dialog = BookmarkListDialog(self.bookmarks, self)
            dialog.bookmarkSelected.connect(self.jump_to_bookmark)
            dialog.bookmarkDeleted.connect(self.delete_bookmark)
            dialog.exec()
        except Exception as e:
            print(f"显示书签列表失败: {str(e)}")
            QMessageBox.warning(self, "错误", f"显示书签列表失败: {str(e)}")

    def jump_to_bookmark(self, bookmark):
        """跳转到书签位置"""
        try:
            # 如果不在同一章节，先切换章节
            if bookmark['chapter_index'] != self.current_chapter_index:
                self.show_chapter(bookmark['chapter_index'])
            
            # 等待内容加载完成
            QTimer.singleShot(100, lambda: self._do_jump_to_bookmark(bookmark))
            
        except Exception as e:
            print(f"跳转到书签失败: {str(e)}")

    def _do_jump_to_bookmark(self, bookmark):
        """执行书签跳转"""
        try:
            # 设置光标位置
            cursor = self.content_edit.textCursor()
            cursor.setPosition(bookmark['start_pos'])
            cursor.setPosition(bookmark['end_pos'], QTextCursor.MoveMode.KeepAnchor)
            
            # 设置选中
            self.content_edit.setTextCursor(cursor)
            
            # 确保可见
            self.ensure_cursor_visible()
            
        except Exception as e:
            print(f"执行书签跳转失败: {str(e)}")

    def delete_bookmark(self, bookmark_id):
        """删除书签"""
        try:
            # 找到要删除的书签
            bookmark = next((b for b in self.bookmarks if b['id'] == bookmark_id), None)
            if bookmark:
                # 移除格式
                cursor = QTextCursor(self.content_edit.document())
                cursor.setPosition(bookmark['start_pos'])
                cursor.setPosition(bookmark['end_pos'], QTextCursor.MoveMode.KeepAnchor)
                
                format = QTextCharFormat()
                format.setUnderlineStyle(QTextCharFormat.UnderlineStyle.NoUnderline)
                cursor.mergeCharFormat(format)
                
                # 从列表中移除
                self.bookmarks = [b for b in self.bookmarks if b['id'] != bookmark_id]
                
                # 保存更改
                self.save_bookmarks()
                
        except Exception as e:
            print(f"删除书签失败: {str(e)}")

    def load_bookmarks(self):
        """加载书签数据"""
        try:
            if not self.current_book:
                return
            
            bookmarks_file = Path("data/bookmarks.json")
            if bookmarks_file.exists():
                with open(bookmarks_file, 'r', encoding='utf-8') as f:
                    data = json.load(f)
                    self.bookmarks = data.get(self.current_book['id'], [])
                
            # 应用所有书签格式
            if self.bookmarks:
                for bookmark in self.bookmarks:
                    if bookmark['chapter_index'] == self.current_chapter_index:
                        self.apply_bookmark_format(
                            bookmark['start_pos'],
                            bookmark['end_pos']
                        )
                
        except Exception as e:
            print(f"加载书签失败: {str(e)}")
            self.bookmarks = []

    def save_bookmarks(self):
        """保存书签数据"""
        try:
            if not self.current_book:
                return
            
            bookmarks_file = Path("data/bookmarks.json")
            bookmarks_file.parent.mkdir(parents=True, exist_ok=True)
            
            # 读取现有数据
            data = {}
            if bookmarks_file.exists():
                with open(bookmarks_file, 'r', encoding='utf-8') as f:
                    data = json.load(f)
            
            # 更新当前书籍的书签
            data[self.current_book['id']] = self.bookmarks
            
            # 保存数据
            with open(bookmarks_file, 'w', encoding='utf-8') as f:
                json.dump(data, f, ensure_ascii=False, indent=2)
            
        except Exception as e:
            print(f"保存书签失败: {str(e)}") 